home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Utilities Professional 1-1500
/
Utilities Professional 1-1500 (1994)(WPD)[!].iso
/
12511500
/
var1411.dms
/
var1411.adf
/
docs
/
LECasm.doc
< prev
next >
Wrap
Text File
|
1993-07-28
|
55KB
|
1,676 lines
Chapter 2 : LECasm Macro Assembler V1.0
-----------------------------------------
The assembler is not complete yet, see section 2.4.3 for a list of the
directives not yet implemented. There will also be a vast number of bugs
which I haven't found yet, which inevitably arise when writing programs of
this length and complexity. One major thing is that I haven't done any checks
for running out of workspace yet, so always make sure that you have plenty,
otherwise the assembler will definitely crash.
Assembly of the source code may be aborted by hitting CTRL + C. When the
assembler next displays some text (an error), then it will abort the assembly
process, with no output file being written.
In the following chapter, if something is enclosed in square brackets ([,])
then this means that the item is optional. Angled Brackets (<, >) represent
a parameter that you should fill in. Anything else must be included.
2.1 Invoking the Assembler from the CLI
--------------------------------------------
Invoking the assembler from the editor has been dealt with in section 1.9.
The assembler, LECasm, may also be run from the CLI. The format for calling
it is as follows :
LECasm [-<options>] <Source filename> [-<options>]
The Source filename should be the name of the file containing the source
code which you want to assemble. To add options, use a '-' sign, followed by
a list of letter options, as follows :
B - No output file will be produced
C - Set Case independant labels ('help' is equivalent to 'Help')
D - Add a symbol table to the output file (for Debugging)
L - Specify that any output code should be linkable
O<name> - Specify the output filename (name must be immediately after O)
P<name> - Specify the program listing filename (must be immediately after P)
Selecting the name as * will send the listing output to the screen.
Selecting the name as PRT: will send the program listing to the printer.
Q - Pause after assembling (Hit return at CLI, any key from editor)
W<number> - Specify workspace size in bytes. This is the maximum assembled
size of the source code. The number has to be in decimal, and must
immediately follow the option.
X - Add a symbol table to the output file, but only include the symbols
which have been XDEF'd
!<ptr> - Used to link the editor to the assembler. ptr is a pointer to a
structure telling the assembler about the source code, and where to
output the list of errors. Shouldn't be used from the CLI
The default method for assembly, is to have case sensitive labels, produce
an executable file, with its filename based on the source filename, no
listing, no symbol table production, no pausing after assembly, and a
workspace of 60000 bytes. For example,
LECasm -bq test.s
This assembles test.s, produces no binary output, and waits for return to
be pressed after assembly
LECasm -oTest test.s -dw30000
This assembles test.s, produces an executable binary file, with symbol table,
under the name Test, and has a workspace of 30000 bytes
LECasm -dw30000 test.s
This does exactly the same as the above command, but the assembler creates
the output file name from the source filename. This is done via the
following process :
1) If an output file name is specified (via -o), then this is used
2) If the output file contains a period, followed by some letters, then the
last period and the letters following it are removed.
E.g. Test.s => Test TEST.2.asm => TEST.2
3) If no period exists in the filename, then the letters '.exe' are added to
the filename, and this is used.
E.g. Test => Test.exe TEST => TEST.exe
2.2 Source Code Format
---------------------------
The assembler expects each line of the source code to be formatted as
follows :-
[<label>] <opcode> [<operand>[,<operand>] [<comment>]
loop dbra d0,loop wait for a length of time
2.2.1 Label Field
--------------------
Each line does not need a label, and therefore this field can be omitted. A
label must start at column one of the line, otherwise it will be treated as
an opcode. It must start with a letter, a full stop, or an underline
character The next character can be any letter, a digit, a full stop, or an
underline character. A label ends with either a space, a tab, a carriage
return, or a colon. Labels can be up to 230 characters in length. At the
moment, all labels are case sensitive.
E.g. Some legal labels
test, TEST, test1, _test, Test.Me, _test.me.2
E.g. Some illegal labels
1test, tes!t, VeryLongLabelIndeedWhichIsTooLarge
There are some labels which you shouldn't use, and which will cause
problems if you do :-
D0,D1..D6,D7 - May get confused with a data register
A0,A1..A7,SP - May get confused with an address register
SR, CCR - Status register, Condition Control Register,
USP - User Stack Pointer
__LEC - Reserved label for identifying the assembler
__RS - Reserved label which contains the value of the Reserve
Structure counter
NARG - The number of arguments which were supplied to a macro
2.2.1.1 Local Labels
--------------------
Labels can be defined which are local to a certain section of code. A label
is made local by starting it with a period (.). A local label is only valid
between the previous non-local label, and the next non-local label. So for
example :
Wait1 move.w #100,d0 ;wait for a while
.wait dbra d0,.wait
rts
Wait2 move.w #200,d0 ;wait a bit longer
.wait dbra d0,.wait
rts
Here, '.wait' is a local label. The first occurance is attached to subroutine
Wait1, and the second occurance is attached to Wait2.
2.2.2 Opcode Field
---------------------
This field is separated from the label field by means of a tab, a space or
a colon. Entries in this field are one of three types :-
1) A 68000 instruction
2) An assembler directive
3) Macro invocations
Some opcodes can be followed by a size specifier. To size an opcode,
directly after the instruction add a period character (.), and one of the
following size specifiers :-
B - byte sized data (8 bits)
W - word sized data (16 bits)
L - long word sized data (32 bits)
S - short branch specifier
If a size is not specified, then the assembler always assumes that the
instruction is word sized, even if this is not allowed for that instruction.
68000 instructions and assembler directives are case insensitive. Macro
invocations are case sensitive.
2.2.3 Operand Field
----------------------
This is used by those instructions that need parameters. All modes apart
from labels are case insensitive. For 68000 instructions, the following are
recognised :-
Dn - Data Register Direct
An - Address Register Direct
(An) - Address Register Indirect
(An)+ - Address Register Indirect, with postincrement
-(An) - Address Register Indirect, with predecrement
d(An) - Address Register Indirect, with displacement
d(An,Rn.S) - Address Register Indirect, with index
d.S - Absolute short address (.S is equivalent to .W)
d.L - Absolute long address (.L can be omitted)
d(PC) - Program counter with displacement
d(PC,Rn.S) - Program counter with index
#d - Immediate
SR - Status Register (word sized)
CCR - Condition Code Register (byte sized)
USP - User Stack Pointer
Rn/Rn/Rn/Rn
or Rn/Rn-Rn/Rn - Register lists, used for the MOVEM instruction
n = Register number 0 to 7
d = An expression
R = Which register to use (A=address,D=data)
S = Size of register to use (W or L)
In most circumstances, SP can be used as A7 (move.l sp,a0)
2.2.4 Comment Field
----------------------
A space following the Operand field is considered to start a comment. The
Comment itself is totally ignored by the assembler, and should be there for
your benefit. Also, a line starting with a '*', or a ';' is also treated to
be a comment.
2.3 Expressions
--------------------
An expression is a rule for computing a value. It consists of one or more
operands combined by means of an operator. For example :
1+test*4
Here 1, test, 4 are operands, and +, * are the operators.
Spaces in expressions are not allowed, and are treated by the assembler
as the start of the comment field. All values used by the assembler are
treated as signed long words, with no overflow checking being carried out.
An operand may be one of the following :
1) A constant value (E.g. 1, 4)
2) The current value of a label (E.g. test)
The operators which the assembler recognises are as follows :
1) Bitwise not (~) E.g. ~%11010 = %111..11100101
2) Unary negate (-) E.g. -%11010 = %111..11100110
3) Shift left (<<) E.g. %11010<<3 = %11010000
4) Shift right (>>) E.g. %11010>>3 = %11
5) Logic AND (&) E.g. %11010&%11100 = %11000
6) Logic OR (!) E.g. %11010!%11100 = %11110
7) Logic XOR (^) E.g. %11010^%11100 = %00110
8) Multiply (*) E.g. 400*17 = 6800
9) Integer Division (/) E.g. 400/17 = 23
10) Addition E.g. 400+17 = 417
11) Subtraction E.g. 400-17 = 383
12) Equality test E.g. 400=17 = 0 (false)
13) Less than test E.g. 400<17 = 0 (false)
14) Greater than test E.g. 400>17 = -1 (true)
2.3.1 Constants
------------------
The constants of an expression may be in binary, octal, decimal,
hexadecimal, or ascii characters. Binary numbers are specified by a '%' at
the start of the number, octal by '@', hex by '$', and character constants by
single quotes, or double quotes. Character constants must start and end with
the same type of quotes. They are justified to the right, and any unused
bytes are nulled.
For example:
1) Binary Numbers, E.g. %1101, %110101
2) Octal Numbers, E.g. @15, @30071
3) Decimal Numbers, E.g. 13, 12345
4) Hexadecimal Numbers, E.g. $d, $3039
5) Character constants, E.g. "A", '1234'
2.3.2 Labels
---------------
These are a collection of characters in the source code, which represent a
number (either a constant or a relative address). They are used to clarify
the source code, to make hunting for bugs and altering the code much easier.
Predefined labels are as follows :
__LEC - Contains the value 1, and is used for identifying this assembler
__RS - Contains the current value of the reserve structure counter
NARGS - The number of arguments present when calling a macro
* - The current value of the program counter (relative number)
E.g. Suppose you are printing out some text where each page is 66 lines long
You could use the number 66 throughout your code, but it is much clearer to
use a constant,
Lines_Per_Page EQU 66
Now say you want to use sheets of paper 70 lines long, then you only need to
change this one constant, as opposed to changing every line which uses this
constant.
2.3.3 Arithmetic precedence (highest first)
--------------------------------------------
As with normal arithmetical expressions, the assembler recognises that each
operator has a precedence. For example, * is more important (has a greater
precedence) than + and hence a * operator is applied before a + operator, so
1 + 2 * 3 has the value 7, and not 9
Precedence can be overcome by the use of brackets surrounding the section to
be evaluated separately. So
(1 + 2) * 3 has the value 9, and not 7
Where operators have the same precedence, they are applied from left to right.
Thus, since * and / have the same precedence
12 / 2 * 3 has the value 18. not 2.
There follows a list of operation precendences (highest first). Those
operations on the same line have equal precedence.
parentheses, bitwise not (~), unary negate (-)
Shift operations : left (<<), right (>>)
Logic operations : And (&), or (!), Xor (^)
Factors : Multiply (*), Divide (/)
Simple Expression: Add (+), subtract (-)
Comparisons : equality (=), less than (<), greater than (>)
For the comparison operations, a result of 0 means that the comparison was
FALSE. A result of -1 ($ffffffff) means that the comparison was TRUE.
2.3.4 Type Checking
----------------------
The result of an expression yields a value which is one of two different
types. These are Absolute numbers and relative numbers.
1) Absolute numbers are those which are known at assembly time.
E.g. 10, "help"
2) Relative numbers are addresses of parts of your program which are only
known when your program is executing. When a program is run, it may live in
any area of the computers free memory, so references to parts of the program
are stored as offsets relative to the start of the current section, along
with a table of these offsets which are filled in when the program is run.
E.g.
test nop ; test is a relative number, and its value is only
; known when the program is running
To aid debugging, type checking is performed on the operands, when using
certain operators. For example,
test nop
move.l #test+test,d0
The last line will produce the error 'Illegal use of relative arithmetic',
since it is complete nonsense to add two relative numbers together.
There follows a table of all the type checking performed by the assembler
for the various operators. The resulting type of the operation is given in
the columns, with '--' meaning that an error will be displayed.
+------------------------------+
|A op A|A op R |R op A |R op R |
+----------------+------+-------+-------+-------+
|Shift Operation | A | -- | -- | -- |
|Logic Operation | A | -- | -- | -- |
|Factors | A | -- | -- | -- |
|Addition | A | R | R | -- |
|Subtraction | A | -- | R | A |
+-----------------------------------------------+
A = Absolute number; R = Relative number
2.4.1 68000 instructions recognised
--------------------------------------
The following opcodes are taken from the source code, and directly
transfered into numbers which can then be executed by the processor. They can
be entered in either upper or lower case.
ABCD
ADD - ADD is converted to ADDA, ADDI if needed
ADDA,ADDI,ADDQ,ADDX
AND - AND is converted to ANDI if needed
ANDI
ASL,ASR
BRA,BSR,BHI,BLS,BCC,BHS,BCS,BLO,BNE,BEQ,BVC,BVS,BPL,BMI,BGE,BLT,BGT,BLE,
- use bra.s, or bra.b for short branch (2 bytes long)
- use bra, bra.w, or bra.l for word branch (4 bytes long)
BCHG
BCLR
BSET
BTST
CHK
CLR
CMP - CMP is converted to CMPA, CMPI if needed
CMPA,CMPI,CMPM
DBT,DBF,DBRA,DBHI,DBLS,DBCC,DBHS,DBCS,DBLO,DBNE,DBEQ,DBVC,DBVS,DBPL,DBMI
DBGEDBLT,DBGT,DBLE
DIVS,DIVU
EOR - EOR is converted to EORI if needed
EORI
EXG - EXG Ax,Dy is converted to EXG Dy,Ax
EXT
ILLEGAL
JMP,JSR
LEA
LINK
LSL,LSR
MOVE - MOVE is converted to MOVEA if needed
MOVEA,MOVEM,MOVEP,MOVEQ
MULS,MULU
NBCD
NEG,NEGX
NOP
NOT
OR - OR is converted to ORI if needed
ORI
PEA
RESET
ROL,ROR,ROXL,ROXR
RTE
RTR
RTS
SBCD
ST,SF,SHI,SLS,SCC,SHS,SCS,SLO,SNE,SEQ,SVC,SVS,SPL,SMI,SGE,SLT,SGT,SLE
STOP
SUB - SUB is converted to SUBA, SUBI if needed
SUBA,SUBI,SUBQ,SUBX
SWAP
TAS
TRAP
TRAPV
TST
UNLK
2.4.2 Assembler directives
-----------------------------
A directive is a command to the assembler to perform certain actions at
assembly time. These can be commands to turn on or off program listing, or to
include data directly into the object code. The directives can be in either
upper or lower case, even though they are shown here in upper case. Some
directives may be preceeded by a label, if a label is inappropriate for a
directive, and you include one, then the assembler will just ignore it. There
follows a list of possible directives, which are then explained more fully.
Assembly Control Directives
END End of source code
FAIL Produce an error
INCDIR Set search path for files to be included
INCBIN Include binary file
INCLUDE Include source file to be assembled
OPT Set assembler option
ORG Start section for absolute code generation
SECTION Starts a new program section
Conditional Assembly
CNOP Conditional NOP for alignment
EVEN Word align next instruction
ODD Make sure next instruction isn't word aligned
IFEQ Assemble if expression = 0
IFNE Assemble if expression <> 0
IFGT Assemble if expression > 0
IFGE Assemble if expression >= 0
IFLT Assemble if expression < 0
IFLE Assemble if expression <= 0
IFC Assemble if strings match
IFNC Assemble if strings don't match
IFD Assemble if symbol defined
IFND Assemble if symbol not defined
ELSEIF Switches assemby state
Data Definition
DC Define constants
DCB Define Constant Block
DS Define storage
External Symbols
XDEF Define symbols to export
XREF Define symbols to be imported (relative)
XREF.L Define symbols to be imported (absolute)
General Directives
IDNT Change the unit name of a linkable object
Listing Control Directives
LIST Enable listing
NOLIST Disable listing
NOPAGE Stop printing in pages
PAGE Go to next listing page
SPC n Skip n blank lines
LLEN n Set line length (60<=n<=256)
PLEN n Set page length (32<=n<=256)
TTL Set program title
SUBTTL Set program subtitle
LISTCHAR Insert special characters
Macro Directives
MACRO Start a macro definition
ENDM End a macro definition
MEXIT Exit from macro expansion
Repeat Loop Directives
REPT n Begin repeat loop
ENDR end repeat loop
Symbol Definition
= Assign permanent value
EQU Assign permanent value
SET Assign temporary value
REG Assign register list
EQUR Assign register value
RS Reserve structure space
RSRESET Reset the structure offset
RSSET n Set the structure offset to n
Assembly Control Directives
----------------------------
END End of source code
Format: [<label>] END
This directive tells the assembler that the source code has finished, and
any subsequent text is ignored. If you want all of your source code to be
assembled, then this directive can be omitted.
FAIL Produce an error
Format: [<label>] FAIL
This directive produces the error 'FAIL encountered'.
INCDIR Directories to search for files
Format: INCDIR <Search directory>[,<Search directory>]
This directive defines a list of directories that should be searched for
any INCLUDEd files. You can specify as many directories as you like, with
each directory name being separated by a comma (,). The directory may be
enclosed in single (') or double (") quotes. This directive must appear
before any INCLUDE directives.
INCLUDE Include a source file to be assembled
Format: [<label>] INCLUDE <filename>
This directive passes the assembly control to another file, assembles that,
and then continues assembling the origional text. It is equivalent to
inserting the named file in the source code at the position of the directive.
Includes can be nested as many times as memory allows. It is especially
useful for including a standard set of macro definitions, or EQUs in several
different programs. The filename should be in standard amigados format, and
can be enclosed in single (') or double quotes (").
INCBIN Include binary file
Format: [<label>] INCBIN <filename>
This directive reads in the given file, and stores it directly into the
output file. This is useful for including sound/graphics or any other type
of data into your programs, using much less space and being quicker than
using many DC directives. The start of the file is word aligned, as is the
program counter after the file has been included
OPT Set assembler option
Format: OPT <option>[,<option>]
This allows control over various parts of the assembler. The option takes
the form of a letter, or multiple letters, followed by a + or - to turn the
option on and off respectively. The allowed options are as follows:
Option C - Case sensitivity Default: OPT C+
OPT C+ Case sensitive labels
OPT C- Case insensitive lables
This option allows program symbols to be either case sensitive, or case
insensitive. This option should only used at the very beginning of the source
file.
Option D - Include debugging information Default: OPT D-
OPT D+ Include debugging information
OPT D- Exclude debugging information
When an output file is produced by the assembler (executable or linkable),
this option allows the inclusion of a symbol table consisting of all of the
global relative symbols. This information is used by a symbolic debugger to
make debugging of your programs simpler.
Option L - Linkable/executable output Default OPT L-
OPT L+ Generate linkable code
OPT L- Generate executable code
This option should only be used at the very start of the source code.
Option O - Optimisation Default OPT O-
OPT O+ Turn on all optimisations
OPT O- Turn off all optimisations
LECasm is capable of improving certain statements to smaller, quicker
versions. Any optimisations performed by the assembler are reported by
warnings.
With optimisation on, all long backward branches within range will be
converted to short branches. Also any long forward branches within range are
reported with a warning.
After assembly, the number of optimisations performed, and the number of
bytes saved are reported, if any were performed.
Option M - Include macro expansion in listing Default OPT M-
OPT M+ Macro expansions will appear in listing
OPT M- Macro expansions will not appear in listing
By surrounding parts of source code with this option, it is possible to
selectively show the macro expansion in parts of your source.
Option P - Position independence checks Default OPT P-
OPT P+ Enable position independent checks
OPT P- Disable position independent checks
When this option is enabled, all code which requires the use of relocation
information is reported with an error.
Option S - Dump symbol table Default OPT S-
OPT S+ Enable symbol dump
OPT S- Disable symbol dump
With this option enabled, after assembly, the complete symbol table is
dumped either to the screen, or to the program listing. Only the last use
of this option is taken into account.
Option U - Underlines for local labels Default OPT U-
OPT U+ Local labels begin with '_'
OPT U- Local labels begin with '.'
This option allows local labels to begin with an underline instead of a
dot. This option should only be used at the start of the source file.
Option W - Warnings Default OPT W+
OPT W+ Enable warnings
OPT W- Disable warnings
This option allows the disabling of warnings which LECasm produces.
Option X - Export XDEF only Default OPT X-
OPT X+ Export XDEF symbols
OPT X- Export all relative symbols
This option is used in conjunction with option D+. When debugging
information is included, this option allows only the symbols specifically
defined with XDEF to be included in the symbol table.
For example,
OPT d+,x+,o+
enables a symbol to be produced in the output file, with on the symbols
specified with XDEF to be included. All optimisations are also turned on.
ORG Start section for absolute code generation
Format: ORG <expression>
This directive will set the program counter to the value of the expression,
and start a new program SECTION which is position dependant. Programs written
within and ORG section must be first loaded to that same address before the
program will run correctly. So it is not advisable for you to run programs
using this directive from AmigaDOS, as no relocation information is saved
with the program. It is generally used for program which take over control of
the whole machine, and ignore AmigaDOS completely.
Each ORG directive causes a new AmigaDOS SECTION to be created, and it is
up to you to split the assmblers output into the necessary parts.
All labels within an ORG section are absolute, since arithmetic operations
on these labels is valid, which is not the case for AmigaDOS sections. E.g
ORG $47050
Screen ds.b $2710 ;Screen has value $47050
Copper dc.w $e0,Screen>>16 ;Load Bit plane via copper
dc.w $e2,Screen&ffff ;equivalent to dc.w $e0,$4,$e2,$7050
**Rest of copper list**
SECTION Start new program section
Format: [<label>] SECTION <name>[,<type>]
This directives starts a new program section, or hunk.
<name> is the section name (no spaces)
<type> specifies the type of section, and is one of the following :-
CODE - Indicates that the next section contains relocatable code (default)
DATA - Indicates that the next section contains initialised data
BSS - Indicates that the next section contains uninitialised data. In BSS
sections, you can only use the DS directive, to allocate storage space
The type can also be followed by an underscore and a letter to specify which
area of memory the section will live in. These are :-
_F - put this section in FAST memory
_C - put this section in CHIP memory
The default place to store the section is in public memory.
E.g. CODE, DATA_F, BSS_C etc
Conditional Assembly Directives
--------------------------------
CNOP Conditional NOP for alignment
Format: [<label>] CNOP <offset>,<alignment>
This directive aligns the program counter to the given alignment and offset
relative to the start of the section. For standard amigados programs, only
long word alignment can be guaranteed. For example, if you are using a File
Info Block, to Examine a file using the dos library function, this needs to
be long word aligned, so you should write something like the following:
CNOP 0,4
MyInfoBlock ds.b fib_SIZEOF ;Allocate storage for info block
Here MyInfoBlock would be long word aligned. The offset is added to the
program counter after the alignment is made.
CNOP 2,4
This aligns any following code to the word boundary 2 bytes past the
nearest long word aligned boundary.
EVEN word align next instruction
Format: [<label>] EVEN
This directive word aligns the next instruction. This is only necessary
after using dc.b, or ds.b, followed by a label on a line with no directive,
since all other commands automatically perform word alignment. For example
dc.b 1
foo ; foo has an odd address
bar nop ; bar is word aligned by assembler
To word align foo, then put the EVEN directive before the foo label.
ODD Force non-word alignment
Format: [<label>] ODD
This directive sets the program counter to the next odd address. It can
be used to cause a bus error, for example
ODD
foo ; foo has an odd address
bar nop ; bar is word aligned by assembler
Now branching to foo would cause a bus error
IFEQ Assemble if expression = 0
IFNE Assemble if expression <> 0
IFGT Assemble if expression > 0
IFGE Assemble if expression >= 0
IFLT Assemble if expression < 0
IFLE Assemble if expression <= 0
Format: IFxx <expression>
The IFxx range of directives can selectively compile parts of your code,
while ignoring others, depending on the value of the operand. If the
condition is true, then the code following this line is assembled, up to a
matching ENDC. A false condition causes the assembler to skip past the next
lines, until the matching ENDC is found. Conditional assembly can be nested
as many times as you want. These directives are useful for inserting debug
information during development. For example
IFNE DEBUG
opt d+ include debugging info
bsr DisplayDebugInfo
ENDC
IFEQ DEBUG
bsr DisplayNormalScreen
ENDC
If DEBUG has the value 1, the first code fragment would be included, since
1 NE 0 is true. The second code fragment would not be included, since 1 EQ 0
is false.
If you have used high level languages, such as BASIC, C, PASCAL, etc, then
the IF statement in these languages is equivalent to the IFNE directive, and
can be used with the conditional operators as follows :
(remember, a TRUE result gives -1, and a FALSE result gives 0)
IFNE Test=40
this code is assembled if Test has the value 40
ENDC
IFC Assemble if strings match
Format: IFC '<string1>','<string2>'
This directive compares the two strings, and assembles the following code
up to the matching ENDC only if the strings are equal. If the strings are
different, then the lines of code up to the matching ENDC are skipped. The
two strings must be surrounded by single quotes ('), and are case sensitive.
IFNC Assemble if strings don't match
Format: IFNC '<string1>','<string2>'
This directive is the opposite of IFC, the following lines of code being
assembled up the the matching ENDC only if the strings are different.
The last two directives are only useful when using macros, for example you
can check whether an operand has been supplied to a macro by the following:
MoveqD0 MACRO
IFC '','\1' ;if no operand for macro, assume 0
moveq #0,d0
MEXIT
ENDC
moveq #\1,d0 ;otherwise use operand
ENDM
Example uses :
MoveqD0
The fact that there is no operand means that the conditional code is
assembled, and the following code is produceed
moveq #0,d0
MoveqD0 20
Since an operand has been supplied (20), so the the conditional is skipped,
producing the following code :
moveq #20,d0
IFD Assemble if symbol defined
IFND Assemble if symbol not defined
Format: IFD <symbol name>
IFND <symbol name>
These directives selectively assembles or skips the following code up to
the matching ENDC, depending upon whether the symbol has previously been
defined.
ELSEIF Switch assembly state
Format: ELSEIF
This directive toggles the last conditional assembly command. This saves
you from using an ENDC, followed by the opposite condition, so making the
source code more readable. For example
IFEQ test is equivalent to IFEQ test
.... ....
ELSEIF ENDC
.... IFNE test
ENDC ....
ENDC
ENDC End conditional Assembly
Format: ENDC
This directive terminates the current level of conditional assembly.
Data Definition Directives
---------------------------
DC Define constant
Format: [<label>] DC[.<size>] <list>
<label> DC.B <expression>[,<expression>]
<label> DC.W <expression>[,<expression>]
<label> DC.L <expression>[,<expression>]
This directive stores a list of constants into memory. The size of these
constants is specified by the size specifier. Any number of constants can be
stored, separated by commas (,). If no size specifier is given, word size is
assumed. For byte sized constants, strings of ascii characters can also be
stored as follows:
dc.b "can't see the point "
dc.b 'of using "quotes"'
Byte sized constants are not word aligned, whereas word and long word
constants are. References to program labels can only be used in long word
constant blocks, since labels are long words.
DCB Define constant block
Format: [<label>] DCB[.<size>] <number>,<value>
This directive stores the data item given in <value>, the number of times
given by <number>. It is equivalent to having the following line, repeated
<number> times
DC.<size> <value>
For example, DC.W 10,test is equivalent to typing:
DC.W test,test,test,test,test,test,test,test,test,test
DS Reserve structure space
Format: [<label>] DS[.<size>] <expression>
<label> DS.B <expression>
<label> DS.W <expression>
<label> DS.L <expression>
This directive reserves memory locations for later use. All memory
reserved using this directive is initialised to 0. The memory reserved with
DS.B is not word aligned, whereas the memory for DS.W and DS.L are. The
expression denotes the number of bytes, words or long words to reserve.
Forward references to symbols cannot be used in the expression.
INCLUDE Include a source file to be assembled
FORMAT: [<label>] INCLUDE <file name>
This directive passes the assembly control to another file, assembles that,
and then continues assembling the origional text. Include directives can be
nested as many times as memory allows. It is especially useful for including
a standard set of macro definitions, or EQUs in several different programs.
External Symbols
----------------
It is useful to be able to selectively import and export symbols, so that
different modules can use the same labels, but not have to bother about using
local labels. These modules can be from a high level language. All that is
then needed is to link the modules together, with the linker satisfying the
references.
Both absolute and relative symbols can be imported and exported.
XDEF Define an internal label as an external entry
Format: XDEF <label>[,<label>]
Each label defined with the XDEF directive generates an external symbol
definition. This list of symbols can be saved out with the output file when
used in conjunction with the -X assembler option, or OPT X+.
XREF Define a relative symbol defined in another linkable module
XREF.L Define an absolute symbol defined in another linkable module
Format: XREF <label>[,<label>]
XREF.L <label>[,<label>]
These directives define a label which is defined in another program module.
The values of the labels will be resolved later with a linker. The type of
the imported label must be given, otherwise assembler errors will occur.
Only one import is allowed per expression, and must be of the form:
import+<expression>, <expression>+import or import-<expression>
any other forms of expression are illegal.
Note: when executable output is selected, the XREF directive is ignored,
since the imported labels cannot be resolved with a linker, as executable
code does not need to be passed through a linker.
General Directives
------------------
IDNT Change the unit name of a linkable object
Format: IDNT <string>
A program unit consists of one of more sections. This must be given a name,
which is by default ANON_MODULE. This name can be redefined using this
directive. The name can only consist of the characters allowed for a label.
Listing Control Directives
--------------------------
When program listing is selected from the CLI (or editor), then the output
consists of the following if it is a code producing line of source code
1 00.00000020+4e75 RTS end of function
line | Program | generated code line of Source code
number | counter |
| |
Section + appears
number if macro
(hex) expansion
For a line where a value is produced, the following line is produced. This
is for the EQU,SET,IFxx,RS directives.
1=00000020 StarX rs.w 1
line Value of line of Source code
number StarX
The output is also formatted into pages. The first and last lines of a page
are blank to prevent a line of listing spanning two pages of printer paper.
It also constists of a three line title, which is as follows :
LECasm 68000 Macro Assembler V1.0 Page 1
[Either source file assembling, or the name given with the TTL directive]
[Blank, or the name given with the SUBTTL directive]
If program listing is initiated from within the source code, then paging is
disabled.
As this assembler does not perform two full passes on the source code, the
program listing is produced as the source code is being assembled. This means
that when the listing is being produced, there will be some variables which
have undefined values (they are defined later). When this happens, the value
0 is assumed for the listing.
LIST Enable listing
Format: LIST
LIST +
LIST -
The LIST directive by itself will turn on the source code listing. You can
achieve greater control over the listing by using the + and - options. The
assembler maintains a counter, and if it is greater than or equal to zero,
the listing is produced.
LIST + Increments the counter
LIST - Decements the counter
LIST ;Sets the counter to 0
NOLIST Disable listing
Format: NOLIST
This directive sets the listing control counter to -1
NOPAGE Stop printing in pages
Format: NOPAGE
This directive stops the program listing being produced in pages.
PAGE Go to next listing page
Format: PAGE
This sends return characters to the listing until the next page is reached
SPC n Skip n blank lines
Format: SPC <expression>
This will send the number of blank lines given in the expression to the
program listing
LLEN n Set line length (60<=n<=256)
Format: LLEN <expression>
This sets the width of a line of the program listing to the value of the
expression. This must be between 60 and 256
PLEN n Set page length (32<=n<=256)
Format: PLEN <expression>
This sets the Length of a page of the program listing to the value of the
expression. This must be between 32 and 256
TTL Set program title
Format: TTL <name>
This directive sets the title of the listing to the given name, for the
next page of program listing. The name may be enclosed in single or double
quotes.
SUBTTL Set program subtitle
Format: SUBTTL <name>
This directive sets the subtitle of the listing to the given name, for the
next page of program listing. The name may be enclosed in single or double
quotes.
LISTCHAR Insert special characters
Format: LISTCHAR <expression>[,<expression>]
This directive will send the character codes of the expressions to the
program listing. This is useful for setting up the printer to print in
draft mode, with condensed output etc.
Macro Directives
-----------------
MACRO Start a macro definition
FORMAT: <label> MACRO
The macro directive marks the start of a macro definition, which is
terminated by the ENDM directive. The label must be provided, and is used
in place of a directive to invoke the macro expansion. The label must not
include the period (.) character. The source code after the macro directive
is skipped, and only included when the macro is invoked. Invoking the macro
causes the lines of source code after the macro directive to be included at
that point, up to either the end of the macro (marked by ENDM), or a
premature termination of the macro (with MEXIT). Macro definitions cannot
be nested. I.e. you cannot define a macro from within a macro, although you
can call a previously defined macro from within a macro.
Macros are useful for storing sequences of instructions or directives that
are used frequently throughout the program, and replacing them with one line
of source code, which increases the programs readability.
ENDM End a macro definition
FORMAT: ENDM
This directive marks the end of the current macro.
MEXIT Exit from macro expansion
FORMAT: MEXIT
This directive prematurely terminates the expansion of the current macro.
It prevents you from having to use a conditional statement so that the
remainder of the macro up to the ENDM is skipped.
NARG Reserved symbol
This is not a directive, but a label which holds the current number of
arguments which come with the current macro invokation. Outside of a macro
expansion, NARG has the value 0.
Macro Invocation
-----------------
A macro is called by putting the name of the macro in the opcode field of a
line of source code. The operand of the field contains a number of arguments,
separated by commas (,) which are passed onto the macro definition, for
inclusion. You are allowed up to 35 different arguments, which are accessed
in the macro itself by using the backslash character (\) followed by a number
or a letter to select the argument number (1..9,a..z).
E.g \5 is argument 5, \A is argument 10, \S is argument 28
If you want to use spaces, or commas within an argument, then you must
enclose the argument within angled brackets ( < and > ). If when using angled
brackets, you want to include a >, then you must do this by specifying >>.
If a size specifier was supplied with the macro invokation, then this is
stored in parameter \0, and is one of the letters, B, W or L. If no size
specifier was supplied with the invokation, then \0 contains the letter W.
The final parameter usable in a macro is \@ which consists of an underscore
followed by a unique number for that macro. This is useful for defining
labels from within macros. Labels within macros without a unqiue number will
produce the 'Repeated Symbol' error.
If you need to have a \ character in your macro definition, then this can be
achieved by typing \\.
You can call any macro from within another macro, just so long as the macro
you are calling has previously been defined. You can thus have recursive
macros, where the macro calls itself. Macro calls may be nested as deeply as
the macro buffer allows.
The macro buffer is a specific amount of memory set aside for the expansion
of macros. Increasing the buffer size allows you to use bigger macros, as
well as allowing for deeper recursion. The buffer is useful for trapping
recursive macros which have expanded uncontrollably.
For example:
Test MACRO
moveq #0,d0
Test
ENDM
This macro has no terminating condition, and will just harmlessly fill up
the macro buffer, before an error is reported.
Macro Example 1: Calling libraries
When calling the system library functions, the usual approach is as follows:
save the contents of register a6
load a6 with the library base pointer
JSR the routine, offsetting register a6
restore the value of a6
A compact method for doing the above job is via a macro, defined as follows:
LinkLib MACRO
move.l a6,-(sp)
move.l \2,a6 get library base
jsr _LV0\1(a6) Call function
move.l (sp)+,a6
ENDM
Now say you want to allocate some memory using the exec function AllocMem.
The macro call would look as follows :
LinkLib AllocMem,ExecBase
The two arguments would then be transferred into the correct positions in the
macro's code, and line would be assembled as though it were :
move.l a6,-(sp)
move.l ExecBase,a6 get libaray base
jsr _LV0AllocMem(a6) Call function
move.l (sp)+,a6
Macro example 2: Recursion
Suppose you have written a routine called 'print', which displays a message
stored in a0. To write a message, you use the following :
lea Welcome_Message,a0
bsr print
You can write a macro which will print up to five messages out by using the
following recursive macro :
PrintMsg MACRO
IFNC '','\1' ; check for paramter
lea \1,a0 ; display first parameter
bsr print
PrintMsg \2,\3,\4,\5 ; call macro with next 4 parameters
ENDC
ENDM
If you invoke this macro with the following messages :
PrintMsg Welcome_Message,More_Text
This macro call would be expanded as follows :
IFNC '','Welcome_Message'
lea Welcome_Message,a0
bsr print
PrintMsg More_Text,,,,
IFNC '','More_Text'
lea More_Text,a0
bsr print
PrintMsg ,,,,
IFNC '',''
ENDC
ENDM
ENDC
ENDM
ENDC
ENDM
The above lines have been indented to show you the various levels of
recursion.
Macro Example 3: General decremental counter
The 68000 dbra instruction only decrements data registers of word length. A
more general instruction can be created using a macro, and the \0 parameter:
DBG MACRO
IFNE NARG-2 ; check for 2 arguments
FAIL !! Wrong number of arguments !!
MEXIT
ENDC
subq.\0 #1,\1
bcc \2
ENDM
DBG d7,test
This would be expanded to :
IFNE 2-2 ; check for 2 arguments
FAIL !! Wrong number of arguments !!
MEXIT
ENDC
subq.W #1,d7
bcc test
ENDM
The conditional checks to see if two arguments were supplied. If this
wasn't the case, an error would be caused on the line containing the FAIL
instruction, which is printed out. The macro would then be prematurely
terminated by the MEXIT command, with assembly continuing after the macro
invokation.
Since no size specifier was supplied, parameter \0 was assumed to be 'W'
test DBG.l d0,test
This would produce the following assembled code :
test subq.L #1,d0
bcc test
This use of the macro decrements resister d0 as a long word, and when equal
to $ffffffff, stops looping. This demonstrates the use of size specifiers
with macros.
Macro Example 4: Error handling
The following macro is for use after a CMP instruction, and is useful for
error handling. If the result of the compare is not equal to zero, then no
error occured, and the program has to continue with the routine. If the
result is equal to zero, then a message is displayed, and then an error
handling routine is invoked. A macro can be used to achieve this as follows:
ErrIFEQ MACRO
bne.s \@ ; if no error, skip past escape routine
lea \1,a0 ; otherwise display message & escape
bsr print
bra \2
\@
ENDM
jsr _LV0Open(a6) ; open a file using dos library
cmp.l #0,d0
ErrIFEQ NoFile,ErrorHandler
This code fragment would get expanded to :
jsr _LV0Open(a6) ; open a file using dos library
cmp.l #0,d0
bne.s _10 ; if no error, skip past escape routine
lea NoFile,a0 ; otherwise display message & escape
bsr print
bra ErrorHandler
_10
The above code calls the dos library function Open, and if the file doesn't
exist prints a message before transferring control to the error handler. The
\@ parameter has been used to generate a unique label for that macro call, so
that it is possible to branch past the error handling code.
Care must be taken when dealing with the arguments to the macro, otherwise
dangerous side effects may occur. For example, a squaring marco :
square MACRO
\1 set \1*\1
ENDM
test set 2 ; initialise value of test
square test
square test+1
The first call of the macro works correctly, producing the line :
test set test*test
The second call produces an incorrect result, producing the line:
test set test+1*test+1
which is equivalent to 2*test + 1 which is not the same as squaring test.
To solve this problem, the arguments in the macro definition, or the macro
call should have been enclosed in parenthesis. For example, here is the
corrected macro definition :
square MACRO
\1 set (\1)*(\1)
ENDM
Used properly, macros can be an extremely useful tool in making your source
code both readable, and easily maintained.
Repeat Loop Directives
-----------------------
REPT Begin repeat loop
Format: REPT <number>
This directive repeats the block of code surrounded by the REPT and ENDR
directives, the number of times specified by <number>. For example,
moveq #19,d0 Copy 20 long words from (a0)+ to (a1)+
loop move.l (a0)+,(a1)+
dbra d0,loop
A faster version of this, eliminating the loop, and still being as readable
can be done with a loop :
REPT 20
move.l (a0)+,(a1)+
ENDR
If you need labels within a loop, then they must be defined using macros,
to ensure that they are unique for each pass of the loop.
The value of <number> MUST be greater than zero, and cannot contain forward
references to symbols.
ENDR End repeat loop
Format: ENDR
This directive marks the end of the repeat loop.
Symbol Definition Directives
-----------------------------
= Equate symnol value
Format: <label> = <expression>
EQU Equate symbol value
Format: <label> EQU <expression>
The EQU or = directive assigns the value of the expression in the operand
field to the symbol in the label field. The assignment is permanent, and so
you cannot use the label elsewhere in the program. The type of the expression
is given to the label. The expression must only contain previously defined
symbols.
REG Assign register list
Format: <label> REG <register list>
The REG directive allows a symbol to be used in place of a register list,
used in conjunction with the MOVEM instruction. This is usually used to
ensure that registers to be pushed onto the stack at the start of a
subroutine are all popped off again on termination of the routine. E.g.
SubroutineRegs REG d2/d3/a4-a6
Subroutine
movem.l SubroutineRegs,-(sp) ;save registers used by routine
.... code for subroutine ....
movem.l (sp)+,SubroutineRegs ;ensure only regs saved are restored
rts
EQUR Assign register value
Format: <label> EQUR <register>
The EQUR directive allows a symbol to be used in place of a register. The
symbol must be defined before use, and its name cannot contain a period '.'
Only data registers and address registers are allowed. This is used to make
source code more legible. E.g.
Hardware EQUR a6
Colour00 EQU $180
lea $dff000,Hardware
move.w #$fff,Colour00(Hardware)
SET Set symbol value
Format: <label> SET <expression>
The EQU directive assigns the value of the expression in the operand field
to the symbol in the label field. This is identical to EQU, except that the
assignment is temporary. The expression must only contain previously defined
symbols.
RS Reserve Structure Space
Format: [<label>] RS[.<size>] <expression>
<label> RS.B <expression>
<label> RS.W <expression>
<label> RS.l <expression>
This directive is used to define 'C' type structures, as used extensively
by the Amiga Operating System. For example, a list of word numbers may be
defined as follows :-
rsreset ; reset Reserve counter
List_next rs.l 1 ; pointer to next number in list
List_number rs.w 1 ; The value of the number
List_SIZEOF rs.w 0 ; The size of this structure
If you then allocated some memory for this structure, and used register A0
to point to this area of memory, then you can access the variouselements of
the structure, as follows :
move.l List_next(a0),a1 ; a1 points to next structure in list
move.w List_number(a0),d0 ; d0 = value of this number
What this directive actually does is to assign the value of the internal
Reserve space counter to the label, and then increases the value of the
counter by the space allocated in the expression (like with DS). So in
our above example, List_next = 0, List_number = 4, List_SIZEOF = 6
As with DC and DS, byte sized Reserves are not word aligned, whereas
word and long word reserves are.
RSRESET Reset Structure Space counter
Format: RSRESET
This command sets the structure offset to zero
RSSET Set Structure Space counter
Format: RSSET <expression>
This command sets the structure offset counter to the value of the
expression.
RSSET expression
- This command sets the structure offset to the value of the expression. The
numbers in the expression MUST be defined before the expression.
2.4.3 Directives to be added
-------------------------------
Assembly control
BSS Start a BSS section
CODE Start a code section
DATA Start a data section
OFFSET Define offsets
RORG Relocatable origin
2.5 Output file formats
---------------------------
LECasm can produce two different output file types, which are executable
and linkable.
Executable output can be run directly from the CLI by typing its name or
double clicking its icon from workbench.
Linkable output is used when writing larger programs, or when you wish to
link together some assembly code with that of a high level language. The
linker format used is the AmigaDOS standard, and standard linker programs
such as Blink can be used.
Executable output is assumed. Linkable output can be forced by selecting
the -l option at the command line, or using OPT L+ at the very start if your
source code.
3 Error messages
-----------------------
Addressing mode not allowed
The addressing mode you have just tried to use is invalid. E.g.
or.w #20,a0
Bad Filename for program listing
The assembler couldn't open a file for program listing
Bad register list
Used for movem. Must be of form Dn-Dn/An-An, or Dx/Dy/Dz
Can't reserve relative amount of memory
E.g.
help nop
ds.b help ; nonsense
Cannot evaluate expression
You've made a typo when entering an expression
E.g.
help equ 10++10
Cannot nest repeat loops
Cannot SET relative label
E.g.
help nop
help set help+2 ; nonsense
Data too large
E.g.
moveq #2048,d0
Data too small
E.g.
btst #-1,d0
Division by zero
Expected comma
extra characters were found after an operand, instead of a comma
FAIL encountered
The FAIL, or a non-implemented directive was encountered
File not found
Forward reference or unknown variable
used a variable before it was defined, or a type mismatch. E.g.
ds.b help
help equ 10
Illegal branch
Cannot branch short to next instruction. E.g.
bra.s help
help nop
Illegal Label
Labels must start with a letter, '.' or '_'
Illegal use of relative arithmetic
E.g.
help nop
me equ help+help ; nonsense
Instruction not recognised
You've used a non-recognised directive (possible typing error ?)
Invalid directive for BSS section
BSS sections can only reserve memory for use at run-time. So the
only allowable code generating directive is 'ds'
Invalid string
when using IFC or IFNC, the string of characters must be enclosed
by single (') quotes
Line Length must be between 60 and 256
The expression for LLEN must be between the above bounds
Macro used in expression
A macro name was used in an arithmetic expression. For example
Test MACRO
moveq #Test,d0 ;Test is a macro, not a number
ENDM
Missing ENDC
There are more IF's than ENDC's in the source
Missing ENDM
There is a macro defintion without an end of macro directive
Missing ENDR
There is a REPT in the source, without a matching ENDR
Missing Label
EQU, MACRO, SET must have a label
Nested macro definition
You cannot define a macro from within another macro
Out of macro space
The macro buffer has become full, so increase it
Page Size must be between 32 and 256
The expression for PLEN must be between the above bounds
Reading file
Register expected
A register (Dn or An) must follow an EQUR statement. E.g.
test EQU pc
Relative labels used in dc.b,dc.w For example:
test nop
dc.w test ;can't fit relative value of help into a word
Relative labels in different sections For example:
sect1 move.l sect1-sect2,d0
SECTION two
sect2 nop
Relative not allowed
A relative label has been used with a word or byte size specifier
E.g.
move.w #test,a0
test nop
Relative reference to different section
You've tried to access a label in another section relative to the PC
E.g.
lea test(pc),a0
SECTION Another
test nop
Relocation not allowed
The message is for a line using a relocation, when using OPT P+.
(position indendence checks)
Repeated Symbol <symbol>
You've used this symbol before in the program
Size not allowed
The size of your instruction is invalid for that instruction
E.g. move.b #20,a0 ;address registers must be .w or .l
Spurious ELSEIF
An ELSEIF directive was encountered outside of a conditional section
Spurious ENDC
The ENDC directive was encountered outside of a conditional section
Spurious ENDM/MEXIT
An end of MACRO directive was found when not expanding a macro
Spurious ENDR
The ENDR directive was encountered before a REPT directive
Unknown addressing mode
You have made a typing error while entering an addressing mode
Unknown section type
Valid section types are: BSS, CODE, DATA
Unknown size
The size you have used for an instruction is not recognised. E.g.
move.z #10,d0
Unknown symbol <label>
You've used a label which you hasn't been defined
Unmatched parenthesis
You've forgotten a bracket
Workspace too small (increase it)
The size of the output from the assembler is greater than the space
you have allocated. So you must increase the amount of workspace
with -w from the CLI, or the workspace box from the editor
Credits
-------
A Practical Introduction to Pascal with BS 6192 - I.R. Wilson & A.M. Addyman
- I used the syntax diagrams from this to make the Expression handler
Amiga ROM Kernal Reference Manual - Commodore-Amiga Inc.
- Various bits
The AmigaDos Manual - Commodore-Amiga Inc.
- Format for Amiga binary file structure, details about Assem
The Consise Atari ST 68000 Programmer's Reference Guide - Katherine Peel
- I don't care what you say, the ST is a good computer, and anyway, this was
the only book I have which outlined fully the 68000's instruction set. I
never did get round to buying Motorola's book.